package com.atguigu.schedule.service;

import com.atguigu.schedule.common.Result;
import com.atguigu.schedule.pojo.VerificationCode;
import com.atguigu.schedule.mapper.VerificationCodeMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.stream.Collectors;

/**
 * 验证码服务
 * 
 * @author atguigu
 * @since 2024
 */
@Service
public class VerificationCodeService {
    
    @Autowired
    private VerificationCodeMapper codeMapper;
    
    /**
     * 生成验证码
     */
    @Transactional(rollbackFor = Exception.class)
    public Result<Map<String, Object>> generateCode(String phone) {
        try {
            // 1. 检查手机号格式
            if (!isValidPhone(phone)) {
                return Result.build(null, 400, "手机号格式不正确");
            }
            
            // 2. 检查发送频率（1分钟内只能发送一次）
            if (hasRecentCode(phone)) {
                return Result.build(null, 400, "请稍后再试，1分钟内只能发送一次");
            }
            
            // 3. 生成5位随机验证码
            String code = generateRandomCode(5);
            
            // 4. 保存到数据库
            VerificationCode verificationCode = new VerificationCode(phone, code);
            codeMapper.update(verificationCode);
            
            // 5. 记录日志供管理员查看
            System.out.println("=== 验证码生成 ===");
            System.out.println("手机号: " + phone);
            System.out.println("验证码: " + code);
            System.out.println("过期时间: " + verificationCode.getExpireTime());
            System.out.println("================");
            
            // 6. 返回结果（不包含验证码，仅供前端显示）
            Map<String, Object> result = new HashMap<>();
            result.put("phone", phone);
            result.put("expireTime", verificationCode.getExpireTime());
            result.put("message", "验证码已生成，请联系管理员获取");
            
            return Result.ok(result);
            
        } catch (Exception e) {
            System.err.println("生成验证码失败: " + e.getMessage());
            return Result.build(null, 500, "生成验证码失败");
        }
    }
    
    /**
     * 验证验证码
     */
    @Transactional(rollbackFor = Exception.class)
    public Result<Boolean> verifyCode(String phone, String code) {
        try {
            // 1. 查找有效的验证码
            VerificationCode verificationCode = codeMapper.selectValidCode(
                phone, code, LocalDateTime.now());
            
            if (verificationCode == null) {
                return Result.build(false, 400, "验证码错误或已过期");
            }
            
            
            // 2. 标记为已使用
            verificationCode.setUsed(true);
            codeMapper.update(verificationCode);
            
            System.out.println("验证码验证成功 - 手机号: " + phone + ", 验证码: " + code);
            
            return Result.ok(true);
            
        } catch (Exception e) {
            System.err.println("验证验证码失败: " + e.getMessage());
            return Result.build(false, 500, "验证失败");
        }
    }
    
    /**
     * 获取待处理的验证码列表（供管理员查看）
     */
    public Result<List<Map<String, Object>>> getPendingCodes() {
        try {
            // 查找最近1小时内未使用的验证码
            LocalDateTime oneHourAgo = LocalDateTime.now().minusHours(1);
            List<VerificationCode> codes = codeMapper.selectRecentUnusedCodes(oneHourAgo);
            
            List<Map<String, Object>> result = codes.stream()
                .map(code -> {
                    Map<String, Object> item = new HashMap<>();
                    item.put("id", code.getId());
                    item.put("phone", code.getPhone());
                    item.put("code", code.getCode());
                    item.put("createTime", code.getCreateTime());
                    item.put("expireTime", code.getExpireTime());
                    item.put("used", code.getUsed());
                    return item;
                })
                .collect(Collectors.toList());
            
            return Result.ok(result);
            
        } catch (Exception e) {
            System.err.println("获取待处理验证码失败: " + e.getMessage());
            return Result.build(null, 500, "获取失败");
        }
    }
    
    /**
     * 清理过期验证码
     */
    @Transactional(rollbackFor = Exception.class)
    public void cleanExpiredCodes() {
        try {
            codeMapper.deleteExpiredCodes(LocalDateTime.now());
            System.out.println("过期验证码清理完成");
        } catch (Exception e) {
            System.err.println("清理过期验证码失败: " + e.getMessage());
        }
    }
    
    // 辅助方法
    private boolean isValidPhone(String phone) {
        return phone != null && phone.matches("^1[3-9]\\d{9}$");
    }
    
    private boolean hasRecentCode(String phone) {
        LocalDateTime oneMinuteAgo = LocalDateTime.now().minusMinutes(1);
        return codeMapper.existsByPhoneAndCreateTimeAfter(phone, oneMinuteAgo);
    }
    
    private String generateRandomCode(int length) {
        Random random = new Random();
        StringBuilder code = new StringBuilder();
        for (int i = 0; i < length; i++) {
            code.append(random.nextInt(10));
        }
        return code.toString();
    }
}
